<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/9/13
 * Time: 17:38
 */

namespace App\Services;
use App\Exceptions\CouponCodeUnavailableException;
use App\Exceptions\InternalException;
use App\Jobs\CloseOrder;
use App\Models\CouponCode;
use App\Models\Order;
use App\Models\ProductSku;
use App\Models\User;
use App\Models\UserAddress;
use Carbon\Carbon;

class OrderService
{
    public function store(User $user,UserAddress $address, $remark, $items, CouponCode $coupon = null )
    {
        // 如果传入了优惠券，则先检查是否可用
        if ($coupon) {
            // 但此时我们还没有计算出订单总金额，因此先不校验
            $coupon->checkAvailable($user);
        }
        //开启事务
        $order = \DB::transaction(function () use ($user,$address,$remark,$items,$coupon){
            //更新地址最新使用时间
            $address->update(['last_used_at'=> Carbon::now()]);
            //创建订单
            $order = new Order([
                'address' => [
                    'address'       => $address->full_address,
                    'zip'           => $address->zip,
                    'contact_name'  => $address->contact_name,
                    'contact_phone' => $address->contact_phone,
                 ],
                'remark'   => $remark,
                'total_amount' => 0,
            ]);
            //订单关联当前用户
            $order->user()->associate($user);
            $order->save();
            $totalAmount = 0;

            //遍历sku
            foreach ($items as $data){
                $sku = ProductSku::find($data['sku_id']);
                //创建OrderItem 并直接关联订单
                $item = $order->items()->make([
                    'amount' => $data['amount'],
                    'price'  => $sku->price,
                ]);
                $item->product()->associate($sku->product_id);
                $item->productSku()->associate($sku);
                $item->save();
                $totalAmount += $sku->price * $data['amount'];
                if ($sku->decreaseStock($data['amount'] )<= 0){
                    throw new InternalException('该商品库存不足');
                }
            }
            if ($coupon) {
                // 总金额已经计算出来了，检查是否符合优惠券规则
                $coupon->checkAvailable($user,$totalAmount);
                // 把订单金额修改为优惠后的金额
                $totalAmount = $coupon->getAdjustedPrice($totalAmount);
                // 将订单与优惠券关联
                $order->couponCode()->associate($coupon);
                // 增加优惠券的用量，需判断返回值
                if ($coupon->changeUsed() <= 0) {
                    throw new CouponCodeUnavailableException('该优惠券已被兑完');
                }
            }
            //更新订单总额
            $order->update(['total_amount' => $totalAmount]);

            //将下单的商品从购物车移除
            $skuId = collect($items)->pluck('sku_id')->all();
            app(CartService::class)->remove($skuId);


            return $order;
        });

        //这里我们直接使用 dispatch 函数
        dispatch(new CloseOrder($order, config('app.order_ttl')));

        return $order;
    }

}